//
//  NoRotation.m
//  NoRotation
//
//  Created by crash-x on 28.12.08.
//



#include <objc/runtime.h>
#include <objc/message.h>

#import <UIKit/UIDevice.h>

#define PREFIX "nro_"
#define APP_NAME "NoRotation"
#define LOG_NOTHING 0
#define LOG_ERROR 1
#define LOG_WARNING 2
#define LOG_INFO 3
#define LOG_DEBUG 4
#define MAX_LOG_LEVEL 4
#define CONFIG_PATH "/var/mobile/Library/SBSettings/Toggles/NoRotation/NoRotation.plist"

IMP MSHookMessage(Class _class, SEL sel, IMP imp, const char *prefix);

BOOL enabled = NO;
BOOL iPodAlwaysEnabled = NO;
BOOL safariAlwaysEnabled = NO;
BOOL iPodAlwaysDisabled = NO;
BOOL safariAlwaysDisabled = NO;
BOOL safariRotateOnce = NO;
int callTimes = 0;
NSInteger myLogLevel = LOG_DEBUG;

BOOL isIpod = NO;


@protocol RenamedMethods 
- (void)nro_deviceOrientationChanged:(id)event;
- (void)nro_applicationWillSuspend;
@end 


void myLog(int logLevel, NSString * formatString, ...) {
	NSString * logString;
	va_list argumentList;
	char *logLevelStrings[] = {"None", "Error", "Warning", "Info", "Debug"};
	
	if(myLogLevel != LOG_NOTHING && logLevel > MAX_LOG_LEVEL)
		return;
	
	if(logLevel > MAX_LOG_LEVEL || logLevel == LOG_NOTHING)
		return;
	
	if(logLevel > myLogLevel)
		return;
	
	va_start (argumentList, formatString);
	logString = [[NSString alloc] initWithFormat:formatString arguments:argumentList];
	va_end (argumentList);
	
	NSLog(@"%s:%s: %@", APP_NAME, logLevelStrings[logLevel], logString);
	
	[logString release];
}


void __Application__deviceOrientationChanged_(id self, SEL message, id event) {
	myLog(LOG_DEBUG, @"Hooked deviceOrientationChanged: called!");
	
	if(isIpod == NO && safariRotateOnce == YES && callTimes < 2) {
		myLog(LOG_DEBUG, @"callTimes: %d!", callTimes);
		callTimes++;
		[self nro_deviceOrientationChanged: event];
	}
	
	return;
	
}


void __UIApplication__applicationWillSuspend(id self, SEL message) {
	callTimes = 0;
	[self nro_applicationWillSuspend];
}


/* Based on the Hook code from QuickGold */
IMP MyHookMessage(bool instance, const char *className, const char *messageName, IMP newimp) {
	Class _class = objc_getClass(className);
	
	if(instance == NO)
		_class = object_getClass(_class);
	
	if (_class == nil) {
		myLog(LOG_ERROR, @"cannot find class [%s]", className);
		return NULL;
	}
	
	SEL theSEL = sel_getUid(messageName);
	
    if (theSEL == nil) {
		myLog(LOG_ERROR, @"cannot find method [%s %s]", className, messageName);
        return NULL;
    }
	
	return MSHookMessage(_class, theSEL, newimp, PREFIX);
}



__attribute__((constructor))
static void UAFakerInitializer() {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    
    NSString *appId = [[NSBundle mainBundle] bundleIdentifier];
	
	
	NSDictionary *config = [[NSDictionary alloc] initWithContentsOfFile:@CONFIG_PATH];
	
	if (config != nil) {	
		NSString *tmp = [config objectForKey:@"logLevel"];
		if(tmp != nil) {
			myLogLevel = [tmp intValue];
			if(myLogLevel < 0 || myLogLevel > MAX_LOG_LEVEL)
				myLogLevel = LOG_NOTHING;
		} else {
			myLogLevel = LOG_NOTHING;
		}
		
		tmp = [config objectForKey:@"enabled"];
		if(tmp != nil) {
			if([tmp intValue] == 1)
				enabled = YES;
		} 		
		tmp = [config objectForKey:@"iPodAlwaysEnabled"];
		if(tmp != nil) {
			if([tmp intValue] == 1)
				iPodAlwaysEnabled = YES;
		} 	
		tmp = [config objectForKey:@"SafariAlwaysEnabled"];
		if(tmp != nil) {
			if([tmp intValue] == 1)
				safariAlwaysEnabled = YES;
		} 	
		tmp = [config objectForKey:@"iPodAlwaysDisabled"];
		if(tmp != nil) {
			if([tmp intValue] == 1)
				iPodAlwaysDisabled = YES;
		} 	
		tmp = [config objectForKey:@"SafariAlwaysDisabled"];
		if(tmp != nil) {
			if([tmp intValue] == 1)
				safariAlwaysDisabled = YES;
		} 	
		tmp = [config objectForKey:@"SafariRotateOnce"];
		if(tmp != nil) {
			if([tmp intValue] == 1)
				safariRotateOnce = YES;
		} 
		myLog(LOG_DEBUG, @"Loading...");
	} else {
		myLog(LOG_ERROR, @"Wasnt able to open config file!");
		
		[pool release];
		return;
	}

	
	myLog(LOG_INFO, @"Enabled: %d", enabled);
	myLog(LOG_INFO, @"iPodAlwaysEnabled: %d", iPodAlwaysEnabled);
	myLog(LOG_INFO, @"safariAlwaysEnabeld: %d", safariAlwaysEnabled);
	myLog(LOG_INFO, @"iPodAlwaysDisabled: %d", iPodAlwaysDisabled);
	myLog(LOG_INFO, @"safariAlwaysDisabled: %d", safariAlwaysDisabled);
	myLog(LOG_INFO, @"SafariRotateOnce: %d", safariRotateOnce);
	
	if([appId hasSuffix: @"mobilesafari"] && (enabled == YES || safariAlwaysEnabled == YES)) {
		if(safariAlwaysDisabled == NO) {
			myLog(LOG_INFO, @"Loading into Safari!");
			MyHookMessage(YES, "Application", "deviceOrientationChanged:", (IMP)__Application__deviceOrientationChanged_);
			[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
			if(safariRotateOnce)
				MyHookMessage(YES, "UIApplication", "applicationWillSuspend", (IMP)__UIApplication__applicationWillSuspend);
		}

	}
	
	if([appId hasSuffix: @"mobileipod"] && (enabled == YES || iPodAlwaysEnabled == YES)) {
		if(iPodAlwaysDisabled == NO) {
			myLog(LOG_INFO, @"Loading into iPod!");
			MyHookMessage(YES, "MediaPlayerApp", "deviceOrientationChanged:", (IMP)__Application__deviceOrientationChanged_);
			isIpod = YES;
		}
	}
	
	
    [pool release]; 
}
